gusucode.com > VC++视频目标检测演示帧间差分法-源码程序 > VC++视频目标检测演示帧间差分法-源码程序/code/Video Demo/StaticDetect.cpp

    //Download by http://www.NewXing.com
/*******************************************************************
Motion target detection methods in video
Author: jianglong
date: 2006.06
Compiler: Microsoft Visual C++ 6.0 
********************************************************************/
#include "stdafx.h"
//#include "Motiontrack.h"
#include "StaticDetect.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CStatsticDetect::CStatsticDetect(int nwidth, int nheight)
{
	m_nFrame = 0;
	count = 0;
	WIDTH = nwidth;
	HEIGHT = nheight;
	IMAGESIZE = WIDTH*HEIGHT;
	
	m_pCurImage = new BYTE[IMAGESIZE*3];
	memset(m_pCurImage,0,IMAGESIZE*3);
	m_pGrayImage = new BYTE[IMAGESIZE];
	memset(m_pGrayImage,0,IMAGESIZE);
	m_pBackground = new BYTE[IMAGESIZE];
	memset(m_pBackground,0,IMAGESIZE);
	m_pBgImage = new BYTE[IMAGESIZE*3];
	memset(m_pBgImage,0,IMAGESIZE*3);
    m_pDiffImage = new BYTE[IMAGESIZE]; 
	memset(m_pDiffImage,0,IMAGESIZE);
	m_pDetectImage = new BYTE[IMAGESIZE*3];
	memset(m_pDetectImage,0,IMAGESIZE*3);
	m_pBackHistgram = new short int[IMAGESIZE*256];
	memset(m_pBackHistgram,0,IMAGESIZE*256*sizeof(short int));
	m_pTemplate = new UINT[IMAGESIZE];
	memset(m_pTemplate,0,IMAGESIZE*sizeof(UINT));
	m_pPreGrayImage = new BYTE[IMAGESIZE];
	memset(m_pPreGrayImage,0,IMAGESIZE);
	image1 = new BYTE[IMAGESIZE];
	memset(image1,0,IMAGESIZE);
	image2 = new BYTE[IMAGESIZE];
	memset(image2,0,IMAGESIZE);
	image3 = new BYTE[IMAGESIZE];
	memset(image3,0,IMAGESIZE);
	image4 = new BYTE[IMAGESIZE];
	memset(image4,0,IMAGESIZE);
}

CStatsticDetect::~CStatsticDetect()
{
	delete []m_pBackHistgram;
	delete []m_pDiffImage;
	delete []m_pBgImage;
	delete []m_pGrayImage;
	delete []m_pBackground;
	delete []m_pDetectImage;
	delete []m_pCurImage;
	delete []m_pTemplate;
	delete []image1;
	delete []image2;
	delete []image3;
	delete []image4;

}
void CStatsticDetect::ReceiveFrame(int index,BYTE* sBuf, DETECT_METHOD sMethod)
{
	m_nFrame = index;
	memcpy(m_pCurImage,sBuf,WIDTH*HEIGHT*3);
	RGBToYUV(m_pCurImage,m_pGrayImage,WIDTH,HEIGHT);
//	if(index==1256)
//		SaveBmp(m_pGrayImage,WIDTH,HEIGHT,8,index);
	
	switch(sMethod)
	{
	case D_MULDIFFER:
//		ImageCopy(m_pGrayImage, m_nFrame);
//		if(m_nFrame>2)
//		{
//			MDiffImage(m_pDiffImage,WIDTH,HEIGHT,15);
//			DeNoise(m_pDiffImage,WIDTH,HEIGHT);
////			SaveBmp(m_pDiffImage,WIDTH,HEIGHT,8,index);
//		}

		if(m_nFrame>0)
		{
			DiffImage(m_pGrayImage,m_pPreGrayImage,WIDTH,HEIGHT,20);
			DeNoise(m_pDiffImage,WIDTH,HEIGHT);
		}
		memcpy(m_pPreGrayImage,m_pGrayImage,IMAGESIZE);
		break;
	case D_MULMEAN:
		GetMultiData(m_pGrayImage,WIDTH,HEIGHT);
	
		if(m_nFrame>BACK_ALL_NUM)
		{
			if(m_nFrame==(BACK_ALL_NUM+1))
			{
				GetBgImage();
				memset(m_pTemplate,0,IMAGESIZE*sizeof(UINT));
				count = 0;
				SaveBmp(m_pBackground,WIDTH,HEIGHT,8,index);

			}
			else if(m_nFrame%(2*BACK_ALL_NUM)==1) //更新背景图像
			{
				GetBgImage();
				memset(m_pTemplate,0,IMAGESIZE*sizeof(UINT));
				count = 0;
				SaveBmp(m_pBackground,WIDTH,HEIGHT,8,index);

			}
			
			DiffImage(m_pGrayImage,m_pBackground,WIDTH,HEIGHT,THRESHOLD);
			DeNoise(m_pDiffImage,WIDTH,HEIGHT);
		}
		
		break;
	case D_STATISTIC:
		if(m_nFrame%BACK_SEQ_NUM==1)
			SetBgHistgram(m_pBackHistgram,m_pGrayImage,WIDTH,HEIGHT);	
		
		if(m_nFrame>BACK_ALL_NUM)
		{		
			if(m_nFrame==(BACK_ALL_NUM+1))
			{
				GetBgByHistgram(m_pBackHistgram,m_pBackground,WIDTH,HEIGHT);
				memset(m_pBackHistgram,0,WIDTH*HEIGHT*256*sizeof(short int));
			//	SaveBmp(m_pBackground,WIDTH,HEIGHT,8,index);
				
			}		
			else if(m_nFrame%(3*BACK_ALL_NUM)==1) //更新背景图像
			{
				GetBgByHistgram(m_pBackHistgram,m_pBackground,WIDTH,HEIGHT);	
				memset(m_pBackHistgram,0,WIDTH*HEIGHT*256*sizeof(short int));
			//	SaveBmp(m_pBackground,WIDTH,HEIGHT,8,index);
				
			}
			DiffImage(m_pGrayImage,m_pBackground,WIDTH,HEIGHT,THRESHOLD);
			DeNoise(m_pDiffImage,WIDTH,HEIGHT);
			if(index==1257)
				SaveBmp(m_pDiffImage,WIDTH,HEIGHT,8,index);

		}
		break;
	default:
		break;
	}
	
}

void CStatsticDetect::RGBToYUV(BYTE *sRGB,BYTE *sGray,int nWidth, int nHeight)
{
	int i,j;
	for(j=0;j<nHeight;j++)
	{
		for(i=0;i<nWidth;i++)
		{
			sGray[nWidth*j+i]=(11*sRGB[3*(nWidth*j+i)]+59*sRGB[3*(nWidth*j+i)+1]+30*sRGB[3*(nWidth*j+i)+2])/100;
		}
	}

}

void CStatsticDetect::SetBgHistgram(short int *pHistgram, BYTE *sGray,int nWidth, int nHeight)
{
	for(int j=0;j<nHeight;j++)
	{
		for(int i=0;i<nWidth;i++)
		{
			int p=*(sGray+j*nWidth+i)+256*(j*nWidth+i);
			*(pHistgram+p)=*(pHistgram+p)+1;
		}
	}	

}

BOOL CStatsticDetect::GetBgByHistgram(short int *pHistgram,BYTE *sBg,int nWidth,int nHeight)
{
	int j,i,k;
	for(j=0;j<nHeight;j++)
	{
		for(i=0;i<nWidth;i++)
		{
			int c=0; 
			int color=0;
			for(k=0;k<256;k++)
			{
				if(*(pHistgram+256*(j*nWidth+i)+k)>c)
				{
					c=*(pHistgram+256*(j*nWidth+i)+k);					
					color=k;
				}
			}

			*(sBg+j*nWidth+i)=color;

		}
	}	

	for(j=0;j<nHeight;j++)
	{
		for( i=0;i<nWidth;i++)
		{
			memset(m_pBgImage+(nWidth*j+i)*3,*(sBg+j*nWidth+i),3);	
		}
	}

	return TRUE;
}

void CStatsticDetect::DiffImage(BYTE *sGray,BYTE *pGray,int nWidth, int nHeight,int nThreshold)
{
	int i,j;
	for(j=0;j<nHeight;j++)
	{
		for(i=0;i<nWidth;i++)
		{
			int diff=sGray[j*nWidth+i]-pGray[nWidth*j+i];
//			m_pDiffImage[j*nWidth+i] = BYTE(abs(diff));
			
			if(diff>nThreshold||diff<-nThreshold)
			{
				m_pDiffImage[j*nWidth+i]=255;
			}
			else
			{
				m_pDiffImage[j*nWidth+i]=0;
			}
		}
	}
}
void CStatsticDetect::DeNoise(BYTE *sGray,int nWidth, int nHeight)
{
	int mode[3][3] = {-1,0,-1,-1,0,-1,-1,0,-1};
	Erosion(sGray,nWidth,nHeight,mode);
//	Dilation(sGray,nWidth,nHeight,mode);
	Medianfilter_3x3(sGray,nWidth,nHeight);
	for(int j=0;j<nHeight;j++)
	{
		for(int i=0;i<nWidth;i++)
		{
			memset(m_pDetectImage+(nWidth*j+i)*3, *(m_pDiffImage+j*nWidth+i), 3);	
		}
	}

}

void CStatsticDetect::Medianfilter_3x3(BYTE *sGray, int nWidth, int nHeight)
{
	int i,j,k,l,count;
	int ii,mid;
	BYTE mean[9];
	int ImageWidth, ImageHeight;
	ImageWidth = nWidth;
	ImageHeight = nHeight;
	
	BYTE* pBuf=new BYTE[ImageWidth*ImageHeight]; 
	for(i=1;i<ImageHeight-1;i++)
	{
		for(j=1;j<ImageWidth-1;j++)
		{
			count = 0;	
			for(k=-1;k<=1;k++)
			{
				for(l=-1;l<=1;l++)
				{
					mean[count]=sGray[(k+i)*ImageWidth+l+j];
					count++;
				}
			}
			for(k=0;k<9;k++)
			{
				mid=mean[k];
				ii=k;
				for(l=k+1;l<9;l++)
				{
					if(mid>mean[l])
					{
						mid=mean[l];
						ii=l;
					}
				}
				mean[ii]=mean[k];
				mean[k]=mid;
			}
			pBuf[i*ImageWidth+j]= mean[4];
		}
	}
	memcpy(sGray,pBuf,sizeof(BYTE)*ImageWidth*ImageHeight);
	delete []pBuf;
}

void CStatsticDetect::Dilation(BYTE *sGray,int nWidth, int nHeight,int structure[3][3])
{
	BYTE* t_gray = new BYTE[nWidth*nHeight];
	BYTE pixel;
	int i,j,m,n;
	for(j=1;j<nHeight-1;j++)
	{
		for(i=1;i<nWidth-1;i++)
		{
			t_gray[j*nWidth+i] = (BYTE)0;
			for (m = 0;m < 3;m++ )
			{
				for (n = 0;n < 3;n++)
				{
					if( structure[m][n] == -1)
						continue;
					pixel = sGray[(j+(m-2)+1)*nWidth + i + (n-1)];
					if (pixel == 255 )
					{	
						t_gray[j*nWidth+i] = (BYTE)255;
						break;
					}
				}
			}
			
		}
	}
	memcpy(sGray,t_gray,nWidth*nHeight);
	delete []t_gray;
}

void CStatsticDetect::Erosion(BYTE *sGray,int nWidth, int nHeight,int structure[3][3])
{	
	BYTE* t_gray = new BYTE[nWidth*nHeight];
	BYTE pixel;
	int i,j,m,n;
	for(j=1;j<nHeight-1;j++)
	{
		for(i=1;i<nWidth-1;i++)
		{
			t_gray[j*nWidth+i] = (BYTE)255;
			for (m = 0;m < 3;m++ )
			{
				for (n = 0;n < 3;n++)
				{
					if( structure[m][n] == -1)
						continue;
					pixel = sGray[(j+(m-2)+1)*nWidth + i + (n-1)];
					if (pixel == 0 )
					{	
						t_gray[j*nWidth+i] = (BYTE)0;
						break;
					}
				}
			}
			
		}
	}
	memcpy(sGray,t_gray,nWidth*nHeight);
	delete []t_gray;
}

void CStatsticDetect::GetMultiData(BYTE *sGray,int nWidth, int nHeight)
{
    count++;
	for(int j=0;j<nHeight;j++)
		for(int i=0;i<nWidth;i++)
			m_pTemplate[j*nWidth+i]+=sGray[j*nWidth+i];
}

void CStatsticDetect::GetBgImage()
{
	int i,j,t,pixel;
	for(j=0;j<HEIGHT;j++)
	{
		for(i=0;i<WIDTH;i++)
		{
			t = j*WIDTH+i;
			pixel = UINT(m_pTemplate[t]/count+0.5);
			if(pixel>255)
				m_pBackground[t] = BYTE(255);
			else if(pixel<0)
				m_pBackground[t] = BYTE(0);
			else
				m_pBackground[t] = BYTE(pixel);
		}
	}
}

void CStatsticDetect::SaveBmp(BYTE* buffer,int nwidth, int nheight, int bit, int index) 
{	
	//write bmp
	BITMAPFILEHEADER bfh; 
	bfh.bfType=0X4D42;
	bfh.bfSize=(DWORD)(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256 + nheight*nwidth);
	bfh.bfReserved1=0;
	bfh.bfReserved2=0;
	bfh.bfOffBits=(DWORD)(sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
	
	BITMAPINFOHEADER bih;
	bih.biSize=sizeof(BITMAPINFOHEADER);
	bih.biWidth=nwidth;
	bih.biHeight=nheight;
	bih.biPlanes=1;
	bih.biBitCount=bit;
	bih.biCompression=BI_RGB;
	bih.biSizeImage=nheight*nwidth;
	bih.biXPelsPerMeter = 0;
	bih.biYPelsPerMeter = 0;
	bih.biClrUsed = 0;
	bih.biClrImportant = 0;
	
	RGBQUAD palate[256];
	for(int t=0;t<256;t++)
	{
		palate[t].rgbBlue=(BYTE)t;
		palate[t].rgbGreen=(BYTE)t;
		palate[t].rgbRed=(BYTE)t;
		palate[t].rgbReserved=0;
	}
	int bpl = (nwidth*8+31)/32*4;
	int imageSize = nheight*bpl;
	BYTE* imgData = NULL;
	if(bit == 8)
	{
		imgData = new BYTE[imageSize];
		memcpy(imgData, buffer, imageSize);
	}

	if(bit == 24)
	{
		imgData = new BYTE[imageSize*3];
		memcpy(imgData, buffer, imageSize*3);
	}

	CFile fp;
	CString path ;
	path.Format("Frame%03d.bmp",index);
	
	TRY
	{
		fp.Open("F:\\"+path,CFile::modeCreate | CFile::modeWrite);
		fp.Write((LPSTR)&bfh,sizeof(BITMAPFILEHEADER)); //写文件头
		fp.Write((LPSTR)&bih,sizeof(BITMAPINFOHEADER)); //写信息头
		if(bit==8)
			fp.Write((LPSTR)palate,sizeof(RGBQUAD)*256); //写调色板
		fp.Write(imgData,nheight*nwidth);//写数据
	}
	CATCH(CFileException,e)
	{
		THROW_LAST();
	}
	END_CATCH
		
	delete []imgData;
	imgData = NULL;

	fp.Close();
}


void CStatsticDetect::ImageCopy(BYTE *sGray, int m_num)
{
	if(m_num==0) 
	{
		memcpy(image1,sGray,IMAGESIZE);
	}
	else if(m_num==1)
	{
		memcpy(image2,sGray,IMAGESIZE);
	}
	else if(m_num==2)
	{
		memcpy(image3,sGray,IMAGESIZE);
	}
	else if(m_num==4)
	{
		memcpy(image4,sGray,IMAGESIZE);
	}
	else
	{	
		memcpy(image1,image2,IMAGESIZE);
		memcpy(image2,image3,IMAGESIZE);
		memcpy(image3,image4,IMAGESIZE);
		memcpy(image4,sGray,IMAGESIZE);
	}
}

void CStatsticDetect::Subtract(BYTE *nImage, BYTE *nImage1, BYTE *nImage2, int nWidth, int nHeight, int nThresh)
{
	int i,j;
	for(j=0;j<nHeight;j++)
	{
		for(i=0;i<nWidth;i++)
		{
			int t = j*nWidth+i;
			nImage[t] = nImage1[t]-nImage2[t];
			
			if(abs(nImage[t])>nThresh) 
				nImage[t] = 1;
			else
				nImage[t] = 0;
		}
	}
}

void CStatsticDetect::MDiffImage(BYTE *sGray,int nWidth, int nHeight, int nthresh)
{
	BYTE *temp1 = new BYTE[nWidth*nHeight];
	BYTE *temp2 = new BYTE[nWidth*nHeight];
	Subtract(temp1, image1, image3, nWidth, nHeight, nthresh);
	Subtract(temp2, image2, image4, nWidth, nHeight, nthresh);
	
	int i,j;
//		for(j=0;j<nHeight;j++)
//	{
//		for(i=0;i<nWidth;i++)
//		{
//			int t=j*nWidth+i;
//			if(temp1[t]==1)
//				temp1[t] = 255;
//			else
//				temp1[t] = 0;
//
//			if(temp2[t]==1)
//				temp2[t] = 255;
//			else
//				temp2[t] = 0;
//
//		}
//	}
//
//    DeNoise(temp1,WIDTH,HEIGHT);
//	SaveBmp(temp1,WIDTH,HEIGHT,8,7000);
//    DeNoise(temp2,WIDTH,HEIGHT);
//	SaveBmp(temp2,WIDTH,HEIGHT,8,7001);


    bool p;
	for(j=0;j<nHeight;j++)
{
		for(i=0;i<nWidth;i++)
		{
			int t=j*nWidth+i;
			p = temp1[t] && temp2[t];
			if(p)
				sGray[t] = 255;
			else
				sGray[t] = 0;
		}
	}

	delete []temp1;
	delete []temp2;
}